﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Threading;

namespace Model
{
    public class AktuelleAuktion
    {
        private Auktion aktuelle;
        
        private Queue<Auktion> queue;
        private List<string> afsluttedeAuktioner;
        private Queue<string> auktionerString;

        private int timer = 0;
        bool timerStop = true;

        private object laas = new object();
        object objektLås = new object();
        object objektLås2 = new object();

        public delegate void broadcastDelegate(string besked);
        public event broadcastDelegate broadcastEvent;
        public event broadcastDelegate afgivbudEvent;
        public event broadcastDelegate IngenAuktionerEvent;

        public AktuelleAuktion()
        {
            queue = new Queue<Auktion>();
            afsluttedeAuktioner = new List<string>();
            auktionerString = new Queue<string>();
        }
    
        // Sætter den næste auktion i køen til den aktuelle (string listen bruges til at sende auktioner til klienten).
        public void NæsteAuktion()
        {
                aktuelle = queue.Dequeue();
                auktionerString.Dequeue();
        }


        // Hammerslag styrer "første, anden og tredje" broadcastene, gennem en switch som tjekker på en timer der tæller op.
        // Når casen rammes sender den broadcast, og efter 30 sekunder lægger den auktionen i en afsluttede auktioner liste,
        // sætter vores timer til nul, så vi starter forfra. Så ser  den om der er flere auktioner i køen, eller broadcaster
        // at der ikke er flere auktioner til alle klienter og stopper while-løkken.
        
        public void HammerslagsTimer()
        {
            // Anvender 2 "locks" i denne methode, eftersom 'timerStop' skal kunne ændres for at while-loopet kan stoppes.
            lock (objektLås)
            timerStop = false;

            lock (objektLås2)
            {
                while (!timerStop)
                {
                    Thread.Sleep(1000);
                    ++timer;

                    switch (timer)
                    {
                        case 10:
                            broadcastEvent("Første!!");
                            break;
                        case 20:
                            broadcastEvent("Anden!!");
                            break;
                        case 30:
                            broadcastEvent("Tredje!! Solgt til " + aktuelle.NuværendeVinder + " for: " + aktuelle.HøjestePris + " kr.");
                            AfslutAuktion();
                            timer = 0;

                            if (Queue.Count != 0)
                                NæsteAuktion();
                            else
                            {
                                timerStop = true;
                                IngenAuktioner("Der er ingen igangværende auktioner.");
                            }
                            break;

                    }
                }
            }
        }

        // Sætter højeste pris og nuværende vinder igennem Afgivbud(). Så broadcastes det til alle klienter og sætter timer til nul,
        // så den aktuelle auktion starter forfra.
        public void AfgivBud(int beløb, string byder)
        {
            aktuelle.AfgivBud(beløb, byder);
            afgivbudEvent("Nuværende bud er: " + aktuelle.HøjestePris + " og byderen er: " + aktuelle.NuværendeVinder);
            
            lock (objektLås) // Låser først nede ved timeren, eftersom det øvrige i metoden, er låst af i Auktions-Klassen.
            timer = 0;

        }

        // Metode som tilføjer en besked til eventet.
        public void IngenAuktioner (string besked)
        {
            IngenAuktionerEvent(besked);
        }

        // Opretter et auktionsobjekt, med parameterene navn, beskrivelse og pris. Herefter bliver objektet og en string lagt
        // i kø, string bruges til at broadcaste auktionen.
        public void OpretAuktion(string navn, string beskrivelse, int pris)
        {
            string stringAuktion;

            Auktion nyAuktion = new Auktion(navn, beskrivelse, pris);
            stringAuktion = navn + "#" + beskrivelse + "#" + pris;
            queue.Enqueue(nyAuktion);
            auktionerString.Enqueue(stringAuktion);
        }

        // Lægger de afsluttede auktioner i en liste, som kan sendes til klienter efter ønske.
        // Denne methode bliver ikke låst, eftersom den kun kan tilgåes af en tråd.
        public void AfslutAuktion()
        {
            afsluttedeAuktioner.Add(aktuelle.Navn + "#"+ aktuelle.HøjestePris+"#"+aktuelle.NuværendeVinder);
        }

        // Returnerer den aktuelle auktion.
        public Auktion GetAktuelAuktion()
        {
            lock (objektLås)
            return aktuelle;
        }

        // ********* Methoden skal først anvendes i senere Sprint ********

        //public List<string> GetVundneAuktioner(string client)
        //{
        //    List<string> vundneListe = new List<string>();
        //    foreach (string auktion in afsluttedeAuktioner)
        //    {
        //        string[] tjekker = auktion.Split('#');
        //        if (tjekker[2] == client)
        //        {
        //            vundneListe.Add(auktion);
        //        }
        //    }
        //    return vundneListe;
        //}

        #region ***Properties***

        public Queue<Auktion> Queue
        {
            get { lock(objektLås) return queue; }
        }

        public Queue<string> AuktionerString
        {
            get { lock (objektLås) return auktionerString; }
        }

        #endregion
        
    }

    
}
